#include "cesium/stages/monitor.hpp"
#include "cesium/stages/sampler.hpp"
#include "cesium/random_sampler.hpp"
#include "cesium/rng.hpp"
#include "cesium/stages/filewriter.hpp"
#include "cesium/pipeline.hpp"

using namespace Cesium;

typedef RandomSampler<RNG> UniformSampler;

template<typename T>
class VariableRandomDiskMonitor : public Pipeline {
public:
    VariableRandomDiskMonitor(T* var, float frac, const std::string& filename) {
        FileWriterStage* writerStage = new FileWriterStage(filename);
        add(writerStage);

        SamplerStage<UniformSampler>* samplerStage = new SamplerStage<UniformSampler>(UniformSampler(frac), writerStage);
        add(samplerStage);

        monitorStage = new MonitorStage<T>(var, samplerStage);
        add(monitorStage);

        writerStage->unref();
        samplerStage->unref();
    }
    ~VariableRandomDiskMonitor() {
        monitorStage->unref();
        monitorStage = NULL;
    }

    void record() {
        monitorStage->signal();
    }
private:
    MonitorStage<T>* monitorStage;
}; // class VariableRandomDiskMonitor

int main(int argc, char** argv) {

    uint32 counter = 0;

    // With half the samples saved, record called 200x and a 4 byte record,
    // the output file should be approximately 200 * 0.5 * 4 bytes = 400 bytes

    VariableRandomDiskMonitor<uint32> monitor(&counter, 0.5f, "random_counter_monitor.bin");

    for(int i = 0; i < 100; i++) {
        monitor.record();
        counter++;
        monitor.record();
        counter++;
        counter++;
    }

    return 0;
}
